const jwt = require('jsonwebtoken');
const bcrypt = require('bcryptjs');
const { query } = require('./db');

const JWT_SECRET = process.env.JWT_SECRET || 'your-super-secret-jwt-key-change-in-production';
const JWT_EXPIRES_IN = '24h';

// 生成 JWT Token
function generateToken(payload) {
  return jwt.sign(payload, JWT_SECRET, {
    expiresIn: JWT_EXPIRES_IN
  });
}

// 验证 JWT Token
function verifyToken(token) {
  try {
    return jwt.verify(token, JWT_SECRET);
  } catch (error) {
    throw new Error('Invalid token');
  }
}

// 密码加密
async function hashPassword(password) {
  const saltRounds = 10;
  return await bcrypt.hash(password, saltRounds);
}

// 密码验证
async function comparePassword(password, hashedPassword) {
  return await bcrypt.compare(password, hashedPassword);
}

// 从请求头获取 token
function extractTokenFromHeader(authHeader) {
  if (!authHeader) {
    return null;
  }
  
  if (authHeader.startsWith('Bearer ')) {
    return authHeader.substring(7);
  }
  
  return authHeader;
}

// 中间件：验证用户身份
function authenticateToken(handler) {
  return async (req, res) => {
    try {
      const authHeader = req.headers.authorization;
      const token = extractTokenFromHeader(authHeader);
      
      if (!token) {
        return res.status(401).json({
          success: false,
          message: '未提供认证令牌'
        });
      }
      
      const decoded = verifyToken(token);
      req.user = decoded;
      
      return handler(req, res);
    } catch (error) {
      return res.status(401).json({
        success: false,
        message: '无效的认证令牌'
      });
    }
  };
}

// 中间件：验证用户角色
function authorizeRole(roles) {
  return (handler) => {
    return authenticateToken(async (req, res) => {
      if (!roles.includes(req.user.role)) {
        return res.status(403).json({
          success: false,
          message: '权限不足'
        });
      }
      
      return handler(req, res);
    });
  };
}

// 工单权限检查
async function checkTicketPermission(user, ticketId, permissionType) {
  try {
    // 管理员拥有所有权限
    if (user.role === 'administrator') {
      return true;
    }

    // 获取工单信息
    const ticketInfo = await query(
      'SELECT user_id, support_staff_id, status, verification_status FROM tickets WHERE id = ?', 
      [ticketId]
    );
    
    if (ticketInfo.length === 0) {
      return false;
    }

    const ticket = ticketInfo[0];

    // 工单创建者权限
    if (ticket.user_id === user.id) {
      switch (permissionType) {
        case 'read': return true;
        case 'write': return ['pending', 'in_progress'].includes(ticket.status);
        case 'verify': return ticket.verification_status === 'pending'; // 用户可以验证支持人员的解决方案
        case 'admin': return false;
        case 'internal_notes': return false; // 普通用户不能查看内部备注
      }
    }

    // 分配的支持人员权限
    if (ticket.support_staff_id === user.id && ['support', 'operator'].includes(user.role)) {
      switch (permissionType) {
        case 'read': return true;
        case 'write': return true;
        case 'verify': return false; // 支持人员不能验证自己的工作
        case 'admin': return user.role === 'operator';
        case 'internal_notes': return true;
      }
    }

    // 支持角色的通用权限
    if (['support', 'operator'].includes(user.role)) {
      switch (permissionType) {
        case 'read': return true;
        case 'write': return user.role === 'operator' || ticket.support_staff_id === null;
        case 'verify': return user.role === 'operator';
        case 'admin': return user.role === 'operator';
        case 'internal_notes': return true;
      }
    }

    return false;
  } catch (error) {
    console.error('检查工单权限失败:', error);
    return false;
  }
}

// 检查状态流转权限
async function checkStatusTransition(user, fromStatus, toStatus) {
  try {
    const rules = await query(
      `SELECT * FROM ticket_status_transitions 
       WHERE from_status = ? AND to_status = ? AND required_role = ? AND is_allowed = 1`,
      [fromStatus, toStatus, user.role]
    );

    if (rules.length === 0) {
      return {
        allowed: false,
        message: `无权限将工单状态从 "${fromStatus}" 变更为 "${toStatus}"`
      };
    }

    const rule = rules[0];
    return {
      allowed: true,
      requiresVerification: rule.requires_verification,
      verificationRole: rule.verification_role,
      message: 'ok'
    };
  } catch (error) {
    console.error('检查状态流转权限失败:', error);
    return {
      allowed: false,
      message: '权限检查失败'
    };
  }
}

// 检查内部备注可见性权限
function checkInternalNoteVisibility(user, noteVisibility) {
  if (user.role === 'user') {
    return false; // 普通用户不能查看任何内部备注
  }
  
  switch (noteVisibility) {
    case 'admin_only':
      return user.role === 'administrator';
    case 'support_only':
      return ['support', 'operator', 'administrator'].includes(user.role);
    case 'all_internal':
      return ['support', 'operator', 'administrator'].includes(user.role);
    default:
      return false;
  }
}

// 中间件：检查工单权限
function authorizeTicketPermission(permissionType) {
  return (handler) => {
    return authenticateToken(async (req, res) => {
      const ticketId = req.query.id || req.body.ticketId;
      if (!ticketId) {
        return res.status(400).json({
          success: false,
          message: '缺少工单ID'
        });
      }

      const hasPermission = await checkTicketPermission(req.user, ticketId, permissionType);
      if (!hasPermission) {
        return res.status(403).json({
          success: false,
          message: '无权限执行此操作'
        });
      }
      
      return handler(req, res);
    });
  };
}

// 记录操作日志的辅助函数
async function logTicketAction(ticketId, userId, actionType, description, ipAddress, userAgent, fieldChanges = null, oldValues = null, newValues = null) {
  try {
    await query(
      `INSERT INTO ticket_logs (ticket_id, user_id, action_type, action_description, field_changes, old_values, new_values, ip_address, user_agent) 
       VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
      [ticketId, userId, actionType, description, fieldChanges, oldValues, newValues, ipAddress, userAgent]
    );
  } catch (error) {
    console.error('记录操作日志失败:', error);
  }
}

module.exports = {
  generateToken,
  verifyToken,
  hashPassword,
  comparePassword,
  extractTokenFromHeader,
  authenticateToken,
  authorizeRole,
  checkTicketPermission,
  checkStatusTransition,
  checkInternalNoteVisibility,
  authorizeTicketPermission,
  logTicketAction
};